package com.onpositive.knowledge.model.value.audits;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

import com.onpositive.knowledge.model.IHasUniverse;
import com.onpositive.knowledge.model.IUniverse;
import com.onpositive.semantic.model.api.property.IProperty;

public class GeneralAuditResult extends AbstractAuditResult {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -3298398041235183737L;


	public GeneralAuditResult(IProperty prop) {
		super(prop);
	}

	protected Collection<AbstractAuditResult> children = new ArrayList<AbstractAuditResult>();
	protected HashMap<String, AbstractAuditResult>valueAuditResultMap=new HashMap<String, AbstractAuditResult>();
	protected HashMap<String, AbstractAuditResult>universeAuditResultMap=new HashMap<String, AbstractAuditResult>();

	
	public void addChildAudit(AbstractAuditResult o) {
		children.add(o);		
		String propertyId = o.getPropertyId();
		String auditId = o.getAuditId();
		if( auditId == null  )
			valueAuditResultMap.put(propertyId, o);
		else
			universeAuditResultMap.put( auditId, o );
	}
	
	public void removeChildAudit(AbstractAuditResult o) {
		children.remove(o);		
		String propertyId = o.getPropertyId();
		String auditId = o.getAuditId();
		if( auditId == null )
			valueAuditResultMap.remove(propertyId) ;
		else
			universeAuditResultMap.remove( auditId ) ;
	}

	public AbstractAuditResult getResult(String id)
	{
		AbstractAuditResult res = valueAuditResultMap.get(id);
		if( res != null )
			return res;
		
		res = universeAuditResultMap.get(id) ;
		if( res != null )
			return res;
		
		for( AbstractAuditResult aar : children )
		{
			if( !(aar instanceof GeneralAuditResult) )
				continue ;
			
			GeneralAuditResult gar = (GeneralAuditResult) aar ;
			res = gar.getResult(id) ;
			if( res != null )
				return res;
		}
		return null ;
	}

	public AbstractAuditResult[] getChildren() {
		return children.toArray(new AbstractAuditResult[children.size()]);
	}
	
	public<T extends AbstractAuditResult> List<T> getResults( String propertyId , String auditId, Class<T> clazz )
	{
		ArrayList<T> result = new ArrayList<T>() ;
		AbstractAuditResult propResult = valueAuditResultMap.get( propertyId ) ;
		
		if( propertyId == null ){
			if(auditId!= null){
				AbstractAuditResult aar = universeAuditResultMap.get(auditId);
				if( clazz.isInstance(aar) )
					result.add( clazz.cast(aar) ) ;
			}
			else{
				for( AbstractAuditResult aar : children )
					if( clazz.isInstance(aar) )
						result.add( clazz.cast(aar) ) ;
			}
		}
		
		if( propResult != null )
		{
			if( propResult instanceof GeneralAuditResult ){
				
				GeneralAuditResult gResult = (GeneralAuditResult) propResult ;
				return gResult.getResults(null, auditId, clazz) ;				
			}			
			else if( clazz.isInstance( propResult) ){
				result.add( clazz.cast(propResult) ) ;
			} 
		}
		else{			
			for( AbstractAuditResult aar : children )
				if( aar instanceof GeneralAuditResult )
				{
					List<T> resList = ((GeneralAuditResult)aar).getResults(propertyId, auditId, clazz) ;
					if( resList != null ){
					for( Object obj : resList )
						if( obj != null )
							result.add( clazz.cast( obj ) ) ;
					}
				}
		}
		return result.size() > 0 ? result : null ;
	}
	
	public void setUniverse( IUniverse universe )
	{
		super.setUniverse(universe) ;
		for( AbstractAuditResult aar : children )
			aar.setUniverse(universe) ;
	}

}
